<?php
/**
 * ws 优化基础类库
 * @Author   Wcj
 * @DateTime 2019/3/13 17:23
 */

class ws
{
    CONST HOST = '0.0.0.0';
    CONST PORT = 9503;

    private $ws = null;

    public function __construct()
    {
        //创建websocket服务器对象，监听0.0.0.0:9503端口
        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        $this->ws->set([
            'enable_static_handler' => true, // 开启静态资源
            'document_root' => '/home/wwwroot/learn_swoole/http_server/web',  // 静态资源目录
//            'worker_num' => 4,  // 工作进程数量
            'task_worker_num' => 4,  // 设置异步任务的工作进程数量
        ]);

        $this->ws->on('open', [$this, 'onOpen']);
        $this->ws->on('message', [$this, 'onMessage']);
        $this->ws->on('receive', [$this, 'onReceive']);
        $this->ws->on('task', [$this, 'onTask']);
        $this->ws->on('finish', [$this, 'onFinish']);
        $this->ws->on('close', [$this, 'onClose']);
        $this->ws->start();
    }

    /**
     * 监听ws连接事件
     * @Author   Wcj
     * @DateTime 2019/3/13 17:27
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request)
    {
        echo '会话id：' . print_r($request->fd, true) . PHP_EOL;
        echo '请求参数：' . print_r($request->get, true) . PHP_EOL;
        echo '服务信息：' . print_r($request->server, true) . PHP_EOL;

        if ($request->fd) {
            //每隔2000ms触发一次
            $tick_id = swoole_timer_tick(2000, function ($timer_id) {
                echo "2秒执行一次【定时器ID-{$timer_id}】" . PHP_EOL;
            });
        }

        $ws->push($request->fd, "欢迎来到聊天室");
    }

    /**
     * 方法名
     * @Author   Wcj
     * @DateTime 2019/3/13 17:29
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame)
    {
        echo "接收到客户端数据：{$frame->data}" . PHP_EOL;

        // 测试task
        $data = [
            'fd' => $frame->fd,
            'data' => $frame->data,
        ];

        // 投递任务
        $ws->task($data);

        // 5秒后回客户端消息
        swoole_timer_after(5000, function () use ($ws, $frame) {
            echo '服务器5秒后执行' . PHP_EOL;
            $ws->push($frame->fd, '这是服务器5秒后发给你的消息');
        });

        $ws->push($frame->fd, "发送消息到客户端: {$frame->data}");
    }

    /**
     * 接收任务
     * @Author   Wcj
     * @DateTime 2019/3/13 17:57
     * @param $ws
     * @param $fd
     * @param $from_id
     * @param $data
     */
    public function onReceive($ws, $fd, $from_id, $data)
    {
        //投递异步任务
        $task_id = $ws->task($data);
        echo "Dispath AsyncTask: id=$task_id\n";
    }

    /**
     * 处理任务
     * @Author   Wcj
     * @DateTime 2019/3/13 17:57
     * @param $ws
     * @param $task_id
     * @param $from_id
     * @param $data
     */
    public function onTask($ws, $task_id, $from_id, $data)
    {
        echo "新的工作任务[id=$task_id]" . PHP_EOL;

        sleep(10);

        //返回任务执行的结果
        $ws->finish("执行完毕, 数据为:" . print_r($data, true));
    }

    /**
     * 结束任务
     * @Author   Wcj
     * @DateTime 2019/3/13 17:57
     * @param $ws
     * @param $task_id
     * @param $data
     */
    public function onFinish($ws, $task_id, $data)
    {
        echo $data;
    }

    /**
     * 监听WebSocket消息事件
     * @Author   Wcj
     * @DateTime 2019/3/13 17:57
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd)
    {
        echo "client-{$fd} is closed\n";
    }
}

$obj = new ws();